package org.hank.compose_yyzs.viewmodel

import android.util.Base64
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.franmontiel.persistentcookiejar.PersistentCookieJar
import com.franmontiel.persistentcookiejar.cache.SetCookieCache
import com.franmontiel.persistentcookiejar.persistence.SharedPrefsCookiePersistor
import com.google.gson.Gson
import com.orhanobut.logger.Logger
import com.tencent.mmkv.MMKV
import org.hank.compose_yyzs.constants.HttpConfig
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.launch
import okhttp3.FormBody
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.logging.HttpLoggingInterceptor
import org.hank.compose_yyzs.BuildConfig
import org.hank.compose_yyzs.MyApp
import org.hank.compose_yyzs.R
import org.hank.compose_yyzs.bean.MerchantInfo
import org.hank.compose_yyzs.bean.request.LoginDto
import org.hank.compose_yyzs.bean.response.LoginResponse
import org.hank.compose_yyzs.constants.Constants
import org.hank.compose_yyzs.http.ApiService
import org.hank.compose_yyzs.http.TokenInterceptor
import org.hank.compose_yyzs.utils.NetWorkUtils.generateMessageByException
import org.hank.compose_yyzs.utils.RsaUtils
import org.hank.compose_yyzs.utils.getStringGlobal
import org.hank.compose_yyzs.utils.toJson
import retrofit2.HttpException
import java.nio.charset.Charset
import java.util.concurrent.TimeUnit
import javax.inject.Inject

//  ┏┓　　　┏┓
//┏┛┻━━━┛┻┓
//┃　　　　　　　┃
//┃　　　━　　　┃
//┃　┳┛　┗┳　┃
//┃　　　　　　　┃
//┃　　　┻　　　┃
//┃　　　　　　　┃
//┗━┓　　　┏━┛
//    ┃　　　┃                  神兽保佑
//    ┃　　　┃                  永无BUG！
//    ┃　　　┗━━━┓
//    ┃　　　　　　　┣┓
//    ┃　　　　　　　┏┛
//    ┗┓┓┏━┳┓┏┛
//      ┃┫┫　┃┫┫
//      ┗┻┛　┗┻┛
/**
 *@auth: Hank
 *邮箱: cs16xiaoc1@163.com
 *创建时间: 2023/5/31 14:57
 *描述:
 */
@HiltViewModel
class LoginViewModel @Inject constructor(
    val apiService: ApiService
) : ViewModel() {
    private var _userAccount = MutableStateFlow("admin")
    private var _userPass = MutableStateFlow("111111")
    private val _viewEvents = Channel<LoginViewEvent>(Channel.BUFFERED)
    val viewEvents = _viewEvents.receiveAsFlow()

    val userAccount
        get() = _userAccount.asStateFlow()

    val userPass
        get() = _userPass.asStateFlow()

    fun onAccountChange(str: String) {
        _userAccount.value = str
    }

    fun onPassChange(str: String) {
        _userPass.value = str
    }

    fun login() {
        if (_userAccount.value.isEmpty()) {
            viewModelScope.launch {
                _viewEvents.send(LoginViewEvent.ErrorMessage(getStringGlobal(R.string.login_user_empty_tips)))
            }
            return
        }
//        if (!_userAccount.value.matches(Regex(Constants.phoneReg))) {
//            viewModelScope.launch {
//                _viewEvents.send(LoginViewEvent.ErrorMessage(getStringGlobal(R.string.login_user_err_tips)))
//            }
//            return
//        }
        if (_userPass.value.isEmpty()) {
            viewModelScope.launch {
                _viewEvents.send(LoginViewEvent.ErrorMessage(getStringGlobal(R.string.login_pass_empty_tips)))
            }
            return
        }

        viewModelScope.launch(Dispatchers.IO) {
            var auth = Base64.encodeToString(
                "${Constants.clientId}:${Constants.clientSecret}".toByteArray(
                    Charset.forName("UTF-8")
                ), Base64.DEFAULT
            ).trim()
            var loginDto = LoginDto()
            loginDto.apply {
                username = _userAccount.value!!
                password = _userPass.value!!
                scope = "server"
                grant_type = "password"
                code = "mobile"
            }

            val client = buildHttpClient()

            val builder = Request.Builder()

            val formBody = FormBody.Builder()
                .add("username", loginDto.username)
                .add("password", loginDto.password)
                .add("scope", loginDto.scope)
                .add("code", "mobile")
                .add("grant_type", loginDto.grant_type)
                .build()
            var newRequest: Request =
                builder
                    .addHeader("Authorization", "Basic $auth")
                    .addHeader("Tenant-id", "1")
                    .get()
                    .url(HttpConfig.BASE_URL_SHUJIANG + "auth/oauth2/token")
                    .post(formBody)
                    .build()
            try {
                var response = client.newCall(newRequest).execute()
                var bodyString = response.body.string()
                var wrapBean =
                    Gson().fromJson(bodyString, LoginResponse::class.java)
                if (wrapBean.msg.isNullOrEmpty() && response.code == 200) {
                    MMKV.defaultMMKV().putString(Constants.TOKEN, wrapBean.access_token)
                    MMKV.defaultMMKV().putInt(Constants.USER_ID, wrapBean.user_id)
                    Thread.sleep(100)
                    _viewEvents.send(LoginViewEvent.LoginSuccess)
                } else {
                    _viewEvents.send(LoginViewEvent.ErrorMessage(wrapBean.msg ?: wrapBean.error!!))
                }
            } catch (throwable: Throwable) {
                if (throwable is HttpException) {
                    var errBodyStr = throwable.response()?.errorBody()?.byteString()
                    var wrapBean = Gson().fromJson<LoginResponse>(
                        errBodyStr!!.toString(),
                        LoginResponse::class.java
                    )
                    _viewEvents.send(LoginViewEvent.ErrorMessage(wrapBean.msg ?: wrapBean.error!!))
                } else {
                    _viewEvents.send(LoginViewEvent.ErrorMessage(throwable.message ?: ""))
                }
            }
        }
    }

    fun buildHttpClient(): OkHttpClient {
        var interceptor = HttpLoggingInterceptor()
        interceptor.level = HttpLoggingInterceptor.Level.BODY
        var cookieJar =
            PersistentCookieJar(
                SetCookieCache(),
                SharedPrefsCookiePersistor(MyApp.context)
            )
        val builder = OkHttpClient.Builder()
            .readTimeout(5000L, TimeUnit.MILLISECONDS)
            .writeTimeout(5000L, TimeUnit.MILLISECONDS)
            .connectTimeout(5000L, TimeUnit.MILLISECONDS)
            .cookieJar(cookieJar)

        builder.addInterceptor(TokenInterceptor())
        if (BuildConfig.DEBUG)
            builder.addInterceptor(interceptor)
        return builder.build()
    }
}
sealed class LoginViewEvent {
    data class ErrorMessage(val message: String) : LoginViewEvent()
    object LoginSuccess : LoginViewEvent()
}

